package service

import (
	"crypto/rand"
	"e-commerce/services/auth-service/internal/repository"
	"e-commerce/services/auth-service/internal/token"
	"encoding/base64"
	"errors"
	"log"
	"strconv"

	servicetoken "e-commerce/services/auth-service/api/servietoken"

	"golang.org/x/crypto/bcrypt"
)

type AuthService struct {
	UserRepo *repository.UserRepository
	// Mq       *mq.RabbitMQ
	Cache *token.TokenCache
}

// 生成随机 Token
func generateToken() (string, error) {
	b := make([]byte, 32)
	if _, err := rand.Read(b); err != nil {
		return "", err
	}
	return base64.URLEncoding.EncodeToString(b), nil
}

// 注册用户
func (s *AuthService) Register(username, password string) error {
	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
	if err != nil {
		return err
	}
	return s.UserRepo.CreateUser(username, string(hashedPassword))
}

func (s *AuthService) Login(username, password string) (string, error) {
	user, err := s.UserRepo.GetUserByUsername(username)
	if err != nil {
		return "", errors.New("用户名或密码错误")
	}
	if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)); err != nil {
		return "", errors.New("密码错误")
	}
	token, err := generateToken()
	if err != nil {
		return "", err
	}
	err = s.Cache.Set(token, strconv.Itoa(user.ID), user.Role)
	if err != nil {
		return "", err
	}
	return token, nil
}

// 登出，发布消息到 RabbitMQ
func (s *AuthService) Logout(token string) error {
	exists, userID, role := s.Cache.Get(token)
	if !exists {
		return errors.New("token不存在")
	}
	// s.Mq.PublishLogout(userID)
	s.Cache.Delete(token)
	log.Printf("用户%s,角色%s,登出", userID, role)
	return nil
}

// 校验 Token
func (s *AuthService) ValidateToken(tokenString string) (bool, string, string) {
	service, ok := servicetoken.ValidateToken(tokenString)
	if ok {
		return true, service, ""
	}

	return s.Cache.Get(tokenString)
}

// 删除用户
func (s *AuthService) Remove(token string) error {
	exists, userID, role := s.Cache.Get(token)
	if !exists {
		return errors.New("token不存在")
	}
	userIDInt, err := strconv.Atoi(userID)
	if err != nil {
		return err
	}
	err = s.UserRepo.DeleteUser(userIDInt)
	if err != nil {
		return err
	}
	s.Cache.Delete(token)
	log.Printf("用户%s,角色%s,删除", userID, role)
	return nil
}

func NewAuthService(configPath string) (*AuthService, error) {
	userRepo, err := repository.NewUserRepository(configPath)
	if err != nil {
		return nil, err
	}
	// mq := mq.NewRabbitMQ(configPath)
	cache, err := token.NewRedisClient(configPath)
	if err != nil {
		return nil, err
	}
	return &AuthService{
		UserRepo: userRepo,
		// Mq:       mq,
		Cache: cache,
	}, nil
}
